package com.wlc.kugoudownload;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.io.FileUtils;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.util.regex.Pattern.compile;

/**
 * @author 王立朝
 * @description
 * @date 2021-11-11 12:39:00
 */
public class SpiderKugou {

    /**
     * 1.歌曲的hash值 [正则匹配]
     * 2.歌曲的album_id [正则匹配]
     * 3.歌名 [正则匹配]
     * 4.歌曲下载地址 [正则匹配]
     * 5.unicode转中文 [正则匹配]
     */
    private static final String hashRegex = ",\"hash\":\"(.*?)\",\"brief\":";
    private static final String albumIdRegex = "\"album_id\":(.*?),\"hash\"";
    private static final String audioNameRegex = "\"audio_name\":\"(.*?)\",\"have_album\"";
    private static final String playUrlRegex = "\"play_url\":\"(.*?)\",\"authors\":";
    private static final String unicodeRegex = "(\\\\u(\\p{XDigit}{4}))";

    private static String baseUrl = "https://www.kugou.com/yy/special/single/3953033.html";
    private static String baseUrl2 = "https://www.kugou.com/yy/special/single/3986149.html";
    private static String downloadSrc = "/Users/wanglichao/Documents/music2/";

    public static void main(String[] args) throws Exception {
        System.out.println("下载中...");
        parameter(baseUrl2);
        System.out.println("歌单下载已完成！");
    }

    /**
     * 爬取歌单的每一首歌曲
     *
     * @param baseUrl 酷狗歌单链接地址
     * @throws Exception
     */
    public static void parameter(String baseUrl) throws Exception {
        //JSON工具
        ObjectMapper mapper = new ObjectMapper();
        //获取歌单的Document
        Document musicList = Jsoup.connect(baseUrl).get();
        //正则表达式匹配出歌单所有hash和album_id对应的值
        List<String> musicHash = myRegexpList(musicList.toString(), hashRegex);
        List<String> musicId = myRegexpList(musicList.toString(), albumIdRegex);
        for (int i = 0; i < musicId.size(); i++) {
            //调出歌单每首歌的接口
            String mp3 = "https://wwwapi.kugou.com/yy/index.php?r=play/getdata&callback=jQuery191043744424319789976_1628418579111" +
                    "&hash=" + musicHash.get(i) + "&dfid=08yAMj3R2Rtq2vHAnv0NSCKV&mid=94bf13b027c6ce8289bdfa422f5e783e&platid=4" +
                    "&album_id=" + musicId.get(i) + "&_=1628418579112";
            //获取歌曲的doc
            Document musicPlayer = parsUrl(mp3);
            //获取歌曲的歌名
            String unicodeName = myRegexpOne(musicPlayer.toString(), audioNameRegex);
            //将unicode编码的歌名转换为中文
            String musicName = unicodeToString(unicodeName);
            //将接口的数据转为JSON对象
            String mp3Doc = mapper.writeValueAsString(musicPlayer.body().text());
            //转JSON有反斜杠，将反斜杠替换掉即可
            mp3Doc = mp3Doc.replaceAll("\\\\", "");
            //得到歌曲下载地址
            String playUrl = myRegexpOne(mp3Doc, playUrlRegex);
            //下载
            downLoadMusic(playUrl, musicName);
            System.out.println((i + 1) + "--->【" + musicName + "】 ＞ω＜ 下载完成");
            Thread.sleep(1000);
        }

    }


    public static void downLoadMusic(String musicUrl,String musicName){
        try {
            System.out.println("\n" + musicName + "源地址->" + musicUrl);
            Connection.Response response = Jsoup.connect(musicUrl)
                    //忽略ContentType
                    .ignoreContentType(true)
                    //解除最大字节限制
                    .maxBodySize(0)
                    //模拟浏览器用户代理
                    .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
                    //执行
                    .execute();
            ByteArrayInputStream stream = new ByteArrayInputStream(response.bodyAsBytes());
            FileUtils.copyInputStreamToFile(stream,new File(downloadSrc + musicName + ".mp3"));
        } catch (Exception e) {
            System.out.println("链接->"+musicUrl+" ＞﹏＜ 下载失败");
            e.printStackTrace();
        }
    }

    /**
     * 获取Doc工具类
     * @param url
     * @return
     * @throws Exception
     */
    public static Document parsUrl(String url) throws Exception {
        try {
            Document document = Jsoup.connect(url)
                    .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
                    .timeout(2000)
                    .get();
            return document;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 正则匹配字符串集合工具类
     * @param str
     * @param keyWords
     * @return
     */
    public static List<String> myRegexpList(String str,String keyWords){
        List<String> list = new ArrayList<>();
        Pattern compile = compile(keyWords);
        Matcher matcher = compile.matcher(str);
        while (matcher.find()) {
            list.add(matcher.group(1));
        }
        return list;
    }

    /**
     * 正则匹配单个字符串工具类
     * @param str
     * @param keyWords
     * @return
     */
    public static String myRegexpOne(String str,String keyWords){
        String result = "";
        Pattern compile = compile(keyWords);
        Matcher matcher = compile.matcher(str);
        while (matcher.find()) {
            result = matcher.group(1);
        }
        return result;
    }

    /**
     * unicode转码中文字符
     * @param str
     * @return
     */
    public static String unicodeToString(String str) {
        Pattern pattern = compile(unicodeRegex);
        Matcher matcher = pattern.matcher(str);
        char ch;
        while (matcher.find()) {
            ch = (char) Integer.parseInt(matcher.group(2), 16);
            str = str.replace(matcher.group(1), ch+"" );
        }
        return str;
    }
}



